﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace GKQC.Common
{
    public class DataTableToModel
    {
        public static List<T> ConvertDataTableToModel<T>(DataTable ThisTable)
        {

            //使用typeof运算符来获取Type对象，只需要提供类型名作为操作数，会返回Type对象的引用
            //var ModelType = typeof运算(XXXClass)希望的Type对象类型;
            var ModelType = typeof(T);
            if (ThisTable == null || ThisTable.Rows.Count == 0)
                return null;
            var ModelList = new List<T>();

            var DataRowCollection = ThisTable.Rows;
            var DataColumnCollection = ThisTable.Columns;
            PropertyInfo[] properties = ModelType.GetProperties();
            string _int = "int";
            string _double = "double";
            string _decimal = "decimal";
            string _string = "string";
            string _long = "long";

            //两层循环来遍历这个二维数组
            //第一层循环，循环行
            foreach (DataRow row in DataRowCollection)//DataRow类的DR表示 DataTable 中的一行数据。
            {
                var a = row[ThisTable.Columns[0]];//a是这个这么多行里的一行，并且每次循环会换一下（相当于各个行组成个数组，a是i，++a）

                var Model = ModelType.Assembly.CreateInstance(ModelType.FullName);//从此程序集中查找某个类型，然后使用系统激活器创建它的实例。FullName获取该类型的完全限定名称，包括其命名空间，但不包括程序集
                //第二层循环，循环每行中的属性
                foreach (var p in properties)//GetType得到运行时的类，GetProperties返回这个类的所有公共属性。在这一行a中，p是这个属性里的一项，并且每次循环会换一下（相当于属性组成个数组，p是i,++p）
                {
                    if (row[DataColumnCollection[p.Name]] is DBNull)//Name获取当前成员的名称。p.Name就是当前行当前列的属性名
                    {
                        //p.SetValue(Model, null,null);
                    }
                    else
                    {
                        string proname = p.PropertyType.Name.ToLower();
                        if (proname == _int)
                            p.SetValue(Model, NvlReturnInt(row[DataColumnCollection[p.Name]]), null);
                        else if (proname == _long)
                            p.SetValue(Model, NvlReturnLong(row[DataColumnCollection[p.Name]]), null);
                        else if (proname == _string)
                            p.SetValue(Model, NvlReturnString(row[DataColumnCollection[p.Name]]), null);
                        else if (proname == _double)
                            p.SetValue(Model, NvlReturnDouble(row[DataColumnCollection[p.Name]]), null);
                        else
                            p.SetValue(Model, row[DataColumnCollection[p.Name]], null);
                    }
                }

                ModelList.Add((T)Model);
            }
            return ModelList;
        }

        public static double NvlReturnDouble(object obj)
        {
            try
            {
                if (obj != null) return obj.ToString().Length == 0 ? 0 : Convert.ToDouble(obj);
                return 0;
            }
            catch
            {
                return 0;
            }
        }

        public static decimal NvlReturnDecimal(object obj)
        {
            try
            {
                if (obj != null) return obj.ToString().Length == 0 ? 0 : Convert.ToDecimal(obj);
                return 0;
            }
            catch
            {
                return 0;
            }
        }

        public static int NvlReturnInt(object obj)
        {
            try
            {
                if (obj != null) return obj.ToString().Length == 0 ? 0 : Convert.ToInt32(obj);
                return 0;
            }
            catch
            {
                return 0;
            }
        }

        public static long NvlReturnLong(object obj)
        {
            try
            {
                if (obj != null)
                    return obj.ToString().Length == 0 ? 0 : Convert.ToInt64(obj);
                return 0;
            }
            catch
            {
                return 0;
            }
        }

        public static string NvlReturnString(object strObject, bool blTrim = false, bool blUpper = false)
        {
            try
            {
                if (strObject == null) return string.Empty;
                var returnString = strObject.ToString();
                if (blTrim) returnString = returnString.Trim();
                if (blUpper) returnString = returnString.ToUpper();
                return returnString;
            }
            catch
            {
                return string.Empty;
            }
        }
    }
}
